安卓开发文档翻译:支持多种屏幕,Supporting Multiple Screens
•.运行安卓的设备有着不同的屏幕尺寸和密度(densities)。
•.妳的应用所运行于其上的屏幕会影响到用户界面。
•.大部分用于将妳的应用适配到当前屏幕的工作都是由系统来做的。
•.妳应当创建与屏幕相关的资源,以便对妳的用户界面做精确控制。
1. 多分辨率
1. 像一个网页设计师一样思考
2. 提供替代资源
3. 图标设计指南
4. 管理虚拟设备
运行安卓 的设备有着不同的屏幕尺寸和密度 。对于应用 来说,安卓系统提供 了 一个跨越所有设备的一致性开发环境, 它处理了将每个应用 的用户界面调整 到适合于当前屏幕 的工作中的大部分。 同时,系统 还提供了一个应用编程接口,使得 妳能够控制妳 的应用的用户界面, 应对 特定的屏幕尺寸 和密度, 以便 将妳的用户界面设计针对不同的屏幕情况进行优化。例如, 在平板上和手机上,妳可能想要显示不同的界面。
尽管系统 会进行缩放和尺寸调整操作以让妳的应用在不同屏幕上都能正常显示,但是, 妳应当努力优化 以让妳的应用在不同屏幕尺寸 和密度条件下达到最佳显示效果。 这样, 妳就让所有设备上都具有最大化的用户体验,并且 妳的用户也会认为妳的应用是专们为 他/她/它 们 的设备设计过的—— 而不是简单地拉伸一下以匹配到 他/她/ 它们的设备上。
按照 本文档中的说明进行实践之后, 妳就能够创建出只用单个 .apk 文件便 能在所有被支持的屏幕上都正确显示并且提供最佳用户体验的应用。
注意 , 安卓3.2引入 了新的应用编程接口 ,使得 妳能够更精确地控制 妳的应用针对不同屏幕尺寸 所使用的布局资源。如果 妳 的应用是专为平板开发的,那么这些新特性尤其重要。 欲知详情,参考 声明针对安卓 3.2 的平板布局 小节 。
本小节概述性地说明了安卓对于多种屏幕的支持情况,包括:对于本文档和应用编程接口中的术语和概念的介绍;系统所支持的屏幕种类的概览;对于相关的应用编程接口和底层的屏幕兼容性特性的概述。
屏幕尺寸
实际的物理尺寸,以屏幕的对角线长度来表示。
简单起见,安卓将所有的实际屏幕尺寸分成4种:小(small)、普通(normal)、大(large)和超大(extra large)。
屏幕密度
在屏幕上指定的物理面积中的像素点个数;通常表示成dpi (每英寸的点数(dots per inch))。例如,相对于“普通”或“高”密度屏幕来说,一个“低”密度的屏幕在指定的物理面积中只有较少的像素点数。
简单起见,安卓将所有实际的屏幕密度分成4种:低(low)、中(medium)、高(high)和超高(extra high)。
方向
从用户的角度看到的屏幕朝向。或者是风景式(landscape),或者是肖像式(portrait),对应的意义就是,屏幕边缘的长度比,或者是宽屏式的,或者是高屏式的。注意,不同设备的默认朝向是不同的,并且,当用户转动设备时其朝向还会动态改变。
分辨 率
屏幕上的物理像素点的总数。当妳加入对多种屏幕尺寸的支持时,应用程序便不再直接与分辨率打交道了;应用程序应当仅仅考虑屏幕尺寸和密度,正如前面对屏幕尺寸和密度的分类那样。
与密度无关的像素( Density-independent pixel ) (dp)
这是妳在定义用户界面布局时应当使用的一个虚拟像素单位,这样可以以一种与密度无关的方式来表达布局维度(尺寸)或位置。
与密度无关的像素,等价于 在160 dpi 的 屏幕上的一个物理像素点的大小, 这是系统针对“中”级密度屏幕所假设的基准密度。 在运行时,系统 会以实际屏幕 的密度来透明 地针对dp 单位进行必要的缩放。 dp单位 到屏幕像素之间的转换是狠简单的: px = dp * (dpi / 160) 。例如, 在一个 240 dpi 的屏幕上, 1 dp 等价于 1.5 个物理像素点。 妳应当在定义程序的用户界面时一直使用 dp单位 , 这样可以确保妳的用户界面在具有不同密度的屏幕上正确显示。
从安卓Android 1.6 (应用编程接口版本4)开始,安卓支持多种屏幕尺寸和密度,用来反映每个设备可能具有的不同屏幕配置情况。妳可以使用安卓系统提供的特性来针对每种屏幕配置情况优化用户界面,这样,可以确保,妳的程序不仅是正常渲染的,还能够在每个屏幕上获得最佳的用户体验。
为了简化妳为多种屏幕设置用户界面的工作,安卓将实际的屏幕尺寸和密度范围分成以下几种:
•. 4种基本 尺寸 :小 ( small ) 、普通 ( normal ) 、大 ( large ) 和超大 ( xlarge )
注意 : 从安卓 3.2 (应用编程接口版本13)开始 , 以上的尺寸划分被 另一种按照可用屏幕宽度来管理屏幕尺寸的技巧替代了 。如果 妳是在为安卓 3.2 及更高版本做开发,那么,参考 针对安卓 3.2来声明平板布局 以了解更多细节。
•. 4种基本 密度 : ldpi ( 低 ) 、 mdpi ( 中 ) 、 hdpi ( 高 ) 和 xhdpi (超高)
这些尺寸和密度划分是以一个基准配置为基础的,即为 普通 尺寸 和 mdpi ( 中等 )密度。 这个基准是按照第一 款安卓手机T-Mobile G1 的屏幕配置来设置的,它拥有一块HVGA 屏幕(直到安卓 1.6为止, 这是安卓支持 的唯一一种屏幕配置 )。
划分 出的每种大致尺寸和密度都会扩展成 一系列的实际屏幕尺寸和密度。例如,两个设备 都将它们的屏幕尺寸报告 为 普通 ,但是 ,真正要 手 动 测量的话,可能 会发现它们的实际屏幕尺寸和长宽比稍微 有些不同。类似 地,两个设备 都将屏幕密度报告为 hdpi 的话,它们的实际像素密度也有可能不同。安卓 会帮助应用程序抽象掉这些 小的不同,所以 妳可以只针对大致划分的尺寸和密度来设计用户界面, 由系统来最终进行那些必要的微调。 图 1展示 了 不同的尺寸和密度是如何被大致分类到不同的尺寸和密度分组中的。
图 1. 展示 了安卓如何将实际尺寸和密度大致划分为4种尺寸和密度 (图片 并不精确 ) 。
当妳针对不同的屏幕尺寸进行用户界面设计的时候,妳会发现每种设计都要求一个最小空间。所以,针对以上说明的每个大致屏幕尺寸,都有一个对应的由系统定义的最小分辨率。这些最小尺寸的单位是"dp"——即为妳应当用来定义布局的单位——这就使得系统可以避免处理屏幕密度的差异。
•. xlarge 屏幕最小尺寸 是 960dp x 720dp
•. large 屏幕最小尺寸 是 640dp x 480dp
•. normal 屏幕最小尺寸 是 470dp x 320dp
•. small 屏幕最小尺寸 是 426dp x 320dp
注意 : 在安卓3.0之前, 还没有定义这些最小屏幕尺寸,所以 ,妳可能会遇到某些设备 在普通和大尺寸之间分类错误。 同时,这些尺寸也是以屏幕的物理分辨率为基础来定义的,所以也会随着设备而改变— —例如, 一个带有系统栏的 1024x720平板, 它的实际程序可用显示空间会稍微小一点,因为 有一些空间被系统栏占用了。
为了将妳的程序的用户界面针对 不同的屏幕尺寸和密度做优化, 妳可以针对任何一种大致尺寸和密度来提供 替代资源 。 一般地, 妳应当针对其中的一些屏幕尺寸提供替代的布局文件, 以及为不同的屏幕密度提供替代的位图文件。 在运行时,系统会依据当前设备屏幕的大致尺寸或密度来使用适当 的资源。
妳不需要针对每种屏幕尺寸和密度的组合都提供替代资源 。系统提供 了稳健的兼容性功能, 会处理好将 妳的程序渲染到任何设备屏幕上的过程中的大部分工作,只要 妳采用 了那些能够 让元素平滑地改变尺寸的 技巧来实现 用户界面( 在下面的 最佳实践 中会说明 )就可以了。
注意 : 用来划分设备 的大致屏幕尺寸和密度的标准是互相独立的。例如, 一个 WVGA 高密度屏幕会被划分成普通尺寸的屏幕,因为 它的物理尺寸与T-Mobile G1 (安卓 的第一款设备,以及屏幕配置的基准 ) 差不多。 另一方面,一个 WVGA 中等密度的屏幕会被划分为一个大尺寸的屏幕。尽管 它提供了相同的分辨率 (相同 的像素点个数 ) ,但是, WVGA 中等密度的屏幕 ,它的屏幕密度要小一些, 这就意味着,每个像素 点的物理尺寸会大一些,因此 ,整个屏幕 就会比基准(普通尺寸)屏幕要大一些。
如果,妳的程序在显示于不同密度的屏幕上的时候都保持着相同的物理尺寸(从用户的角度来看)的话,那么,妳的程序就达到了“密度无关性”。
维持密度无关性是很重要的,因为,不具有这个特性的话,一个用户界面元素(例如一个按钮)在低密度的屏幕上就会显得大一些,在高密度的屏幕上就显得小一些。这种关联到密度的尺寸变化会引起妳的程序中布局和可用性的问题。图2和3展示的是,一个程序在不具有密度无关性和具有密度无关性的情况下的不同表现。
图 2. 示例程序 ,不支持不同密度, 在低、中、高密度屏幕上的显示效果。
图 3. 示例程序 ,狠好地支持不同密度 (具有密度无关 性 ) ,在低、中、高密度屏幕上的显示效果。
安卓系统以两种方式帮助妳的程序取得密度无关性:
•.系统会将dp单位按照当前屏幕的密度来进行适当的缩放
•.在必要的情况下,系统会按照当前的屏幕密度来将绘图对象资源缩放到适当的尺寸
在图 2 中,文字视图 和位图绘图对象的尺寸是以像素( px )为单位来指定的,所以 , 在低密度屏幕上,这些视图看起来就大一些,在高密度的屏幕上,这些视图看起来就小一些。 这是因为,尽管实际 的屏幕尺寸可能是一致的,但是, 高密度的屏幕,每英寸 中包含的像素点数更多 (相同个数 的像素点就会落入 到较小的面积中 ) 。 在图 3 中,布局尺寸数据 是以与密度无关的像素(density-independent pixels)( dp )为单位来指定的。因为 与密度无关的像素的基准是 中等密度的屏幕,所以 , 在拥有中等密度的屏幕上,程序 的显示效果与 图2中的一样。然而 ,对于低密度和高密度的屏幕,系统 将 与密度无关的像素值缩小或放大, 以匹配当前的屏幕。
在大部分情况下, 妳可以通过将所有布局尺寸 值以与密度无关的像素( dp )为单位来指定或者 在适当的情况 下 直接指定成 "wrap_content" 的方式来确保程序 的密度无关性。 这样,系统 就会针对当前屏幕 的密度来计算出适当的缩放因子, 以缩放位图绘图对象 ,并以适当的尺寸显示。
然而,位图的缩放可能会导致模糊或像素化的位图产生,这一点妳可能已经在上面的截屏中看到了。为了避免发生这种事,妳应当针对不同的密度提供替代的位图资源。例如,妳应当针对高密度屏幕提供较高分辨率的位图,系统会使用那些位图,而不是将那些针对中等密度屏幕设计的位图缩放来使用。以下小节会更详细地说明如何针对不同的屏幕配置来应用替代资源。
安卓能够对于多种屏幕提供支持的根本点在于,它能够根据当前屏幕的配置来以一种适当的方式管理好一个程序的布局和位图绘图对象的渲染。系统会做好在每种屏幕上正确地渲染妳的程序的大部分工作,具体地,就是适当地缩放布局以匹配屏幕的尺寸/密度,以及,缩放位图绘图对象以匹配屏幕的密度。然后,要想更好地处理好不同的屏幕配置的话,妳还应当:
•. 在清单(manifest)文件中显式地声明妳的程序所支持的屏幕尺寸
通过声明 妳的程序所支持的屏幕尺寸, 妳可以确保只有那些拥有 妳所支持的屏幕的设备才能下载 妳的程序。声明对于 不同屏幕尺寸的支持, 还能够影响到系统如何 在较大的屏幕上绘制妳的程序——尤其是, 妳的程序是否会运行于 屏幕兼容模式。
要想声明妳的程序所支持的屏幕尺寸,妳应当在清单文件中包含 <supports-screens> 元素 。
•. 针对 不同的屏幕尺寸提供不同的布局
默认情况下,安卓会改变妳的程序的布局,以匹配当前设备的屏幕。在大部分情况下,这样就够了。在其它情况下,妳的用户界面可能看起来不那么好,因而需要针对不同的屏幕尺寸进行调整。例如,在一个较大的屏幕上,妳可能需要调整一下某些元素的位置及尺寸,以利用那些多余的屏幕空间,而在一个较小的屏幕上,妳可能需要仔细调整尺寸,以让所有东西都能够显示出来。
可用来提供与尺寸相关的资源的配置标识符包括: small 、 normal 、 large 和 xlarge 。例如,针对 一个超大屏幕的布局,应当放置到 layout-xlarge/ 目录中。
从安卓 3.2 (应用编程接口版本13)开始 , 以上的尺寸分组已经被废弃了, 妳应当使用 sw<N>dp 配置标识符来定义出 妳的布局资源 所需要的最小可用宽度。例如,如果 妳的多面板平板布局要求屏幕宽度最少 是 600dp ,则,妳应当将它放置于 layout-sw600dp/ 目录 中。关于如何使用 这种新技巧来声明布局资源的信息,在 针对安卓 3.2声明平板布局 小节中有详细说明。 .
•. 针对 不同的屏幕密度提供不同的位图绘图对象
默认情况 下,安卓 会缩放 妳的位图绘图对象( .png 、 .jpg 和 .gif 文件)和 点9 ( Nine-Patch ) 绘图对象( .9.png 文件), 以确保它们在每个设备上都能以适当的物理尺寸来显示。例如,如果 妳的程序 只提供了针对基准屏幕即中等屏幕密度(mdpi)的位图绘图对象的话,则, 在高密度的屏幕上,系统会将这些位图放大, 在低密度的屏幕上,系统会将它们缩小。 这种缩放操作可能会引起位图中的一些不好的现象 (artifacts) 。 为了确保妳的位图以最佳的外观呈现出来, 妳应当包含具有 不同分辨率的替代版本,以应对不同的屏幕密度。
可用于与密度相关的资源的配置标识符包括: ldpi ( 低 ) 、 mdpi ( 中 ) 、 hdpi ( 高 ) 和 xhdpi (超高) 。例如,针对 高密度屏幕的位图应当放置在 drawable-hdpi/ 目录中。
这里使用的尺寸和密度配置标识符与之前在 支持 的屏幕范围 中说明的大致尺寸和密度对应。
注意 : 如果 妳 不熟悉配置标识符,也不熟悉系统是如何使用它们来应用替代资源的,那么,阅读 提供替代资源 以了解更多信息。
在运行时,针对任何给定的资源,系统会按照以下步骤来确保界面在当前屏幕上达到可能的最佳显示效果:
1.系统使用适当的替代资源
基于当前屏幕 的尺寸和密度,系统 会使用妳程序中任何存在的对应的尺寸及密度相关的资源。例如,如果当前设备屏幕 是一个高密度屏幕,则,在程序请求显示一个绘图资源时,系统 会寻找 一个能够最佳地匹配到当前设备的配置的绘图资源目录。取决 于其它的替代资源是否可用,带有 hdpi 标识符的资源目录(例如 drawable-hdpi/ )可能是最佳的匹配,因此系统 会使用此目录中的绘图资源。
2.如果没有可用的匹配资源,则,系统会使用默认资源,并且按照需要来缩放它,以匹配当前屏幕的尺寸和密度。
“默认”资源指的是,不带配置标识符的资源。例如, drawable/ 目录 中的资源就是默认的绘图资源。系统假设默认资源 是针对基准屏幕尺寸和密度来设计的, 即为一个普通屏幕尺寸和中等密度。因此 ,针对 高密度屏幕,系统会将默认密度的资源放大,对应 地,针对低密度屏幕,系统会将默认密度的资源缩小。
然而,如果系统要寻找一个与密度相关的资源而又没能在对应的密度相关目录里找到的话,它不一定会使用默认资源。系统可能会尝试使用其它的密度相关资源目录中的某一个,以使得在缩放时得到更好的效果。例如,假设正在寻找一个低密度的资源而又没找到的话,系统会优先将该资源的高密度版本缩小,因为系统可以轻易地按照0.5的比例将一个高密度资源缩小为一个低密度资源,相对于按照0.75的比例将一个中等密度资源缩小为低密度资源来说,这样产生的毛刺(artifacts)更少。
欲知更多关于安卓如何选择替代资源 来匹配当前设备 的信息, 就阅读 安卓如何寻找 最佳匹配的资源 。
安卓支持多种配置标识符,使得妳可以控制系统如何基于当前设备屏幕的特性来选择替代资源。配置标识符,指的是,一个字符串,妳可以将它追加到安卓项目中的某个资源目录中去,以指定该目录中的资源是针对哪种屏幕配置而设计的。
要想使用一个配置标识符,这样做:
1. 在妳的项目的 res/ 目录中创建一个新目录, 以这种格式来命名: <resources_name>-<qualifier>
•. <resources_name> 是指标准的资源名字 (例如 drawable 或 layout ) 。
•. <qualifier> 是指下面的表1中的某个配置标识符,指定 这些资源将用于哪种屏幕配置(例如 hdpi 或 xlarge )。
妳可以一次性使用多个 <qualifier> —— 以减号分隔开就行了。
2.将适当的与配置相关的资源保存到这个目录中。其中的资源文件必须与默认资源目录中的相应文件命名完全相同。
例如, xlarge 是针对超大屏幕的配置标识符。 当妳将这个字符串追加到某个资源目录名中去的时候(例如 layout-xlarge ), 它就表明,这些资源是用于那些拥有超大屏幕 的设备的。
表 1. 配置标识 符,可用来针对 不同的屏幕配置提供特定的资源。
屏幕特性 |
标识符 |
说明 |
尺寸 |
small |
针对 小 尺寸屏幕的资源。 |
normal |
针对 普通 尺寸屏幕的资源。(这是基准尺寸。) |
|
large |
针对 大 尺寸屏幕的资源。 |
|
xlarge |
针对 超大 尺寸屏幕的资源。 |
|
密度 |
ldpi |
针对低密度( ldpi )屏幕(~120dpi)的资源。 |
mdpi |
针对中等密度( mdpi )屏幕(~160dpi)的资源。(这是基准密度。) |
|
hdpi |
针对高密度( hdpi )屏幕(~240dpi)的资源。 |
|
xhdpi |
针对超高密度( xhdpi )屏幕(~320dpi)的资源。 |
|
nodpi |
针对所有密度屏幕的资源。这些是与密度无关的资源。无论当前屏幕的密度是什么,系统都不会对带有这个标记的资源进行缩放。 |
|
tvdpi |
针对处于mdpi 和hdpi 密度之间的屏幕的资源;大约是213dpi。这并不会被归类到一个“主要”密度分组中去。它主要是针对电视的,大部分应用都不需要它——提供针对mdpi和hdpi的资源就对于大部分应用来说已经足够了,系统会对它们进行适当的缩放。如果妳发现必须提供针对tvdpi 的资源的话,那么,妳应当按照1.33*mdpi 的比例来改变它们的大小。例如,一张针对mdpi 屏幕的100px x 100px的图片,在用于tvdpi 时,应当是133px x 133px。 |
|
朝向 |
land |
针对处于横向(宽比例)模式的屏幕的资源。 |
port |
针对处于竖向(高比例)模式的屏幕的资源。 |
|
长宽比例 |
long |
针对那种相对于基准屏幕配置来说有着一个显著较长或较宽的长宽比例(分别相对于竖向或横向来说)的屏幕的资源。 |
notlong |
针对那种拥有与基准屏幕配置近似的长宽比例的屏幕的资源。 |
注意 : 如果 妳的程序是针对安卓 3.2 及更高版本开发的,则,参考 针对安卓 3.2声明平板布局 小节 , 以了解 妳在针对特定屏幕尺寸声明布局资源时应当使用的新的配置标识符 (而不是表1中的那些尺寸标识符) 的信息。
欲知更多关于这些标识符大致对应于怎样 的实际屏幕尺寸及密度的信息,参考 本文档中前面的 支持 的屏幕范围 。
例如,以下是某个程序中的一组资源目录列表,它们针对不同的屏幕尺寸提供不同的布局设计,针对中等、高和超高密度屏幕提供了不同的位图绘图对象。
res/layout/my_layout.xml // 针对普通屏幕尺寸的布局("默认")
res/layout-small/my_layout.xml // 针对小屏幕尺寸的布局
res/layout-large/my_layout.xml // 针对大屏幕尺寸的布局
res/layout-xlarge/my_layout.xml // 针对超大屏幕尺寸的布局
res/layout-xlarge-land/my_layout.xml // 针对超大屏幕尺寸横向布局
res/drawable-mdpi/my_icon.png // 针对中等密度的位图
res/drawable-hdpi/my_icon.png // 针对高密度的位图
res/drawable-xhdpi/my_icon.png // 针对超高密度的位图
欲知更多关于如何使用替代资源 的信息 以及一个完整的配置标识符列表 (不仅仅针对屏幕配置) 的话,参考 提供替代资源 。
注意 ,安卓系统在运行时进行资源的选择时, 会使用特定的逻辑来决定“最佳匹配”的资源。 也就是说, 妳所使用的标识符不一定要在所有情况下都完全匹配当前的屏幕配置,系统 也有可能会使用它 们 。尤其 是, 在按照尺寸标识符来选择资源时,如果 找不到更好的选择,则,系统 会使用针对比当前屏幕稍小的屏幕而设计的资源(例如, 在必要的情况下,在一个大尺寸的屏幕上会使用一个针对普通尺寸屏幕设计的资源 )。然而 ,如果仅有 的那些资源 都 比当前屏幕 还要大 ,那么,系统 不会使用它们, 而是在找不到其它与当前设备配置相匹配的资源的情况下让妳的程序崩溃(例如,所有 的布局资源都标记为 xlarge,而当前设备却拥有一个普通尺寸的屏幕 )。欲知更多关于系统如何选择资源 的信息,请阅读 安卓如何寻找最佳匹配 的资源 。
提示 : 如果 妳 有 某些不应当由系统来缩放的绘图资源(例如 妳可能会在运行时亲自调整这些图片 )的话,那么 , 妳应当把它们放置在一个带有 nodpi 配置标识符的目录中。 带有这种标识符的资源会被看成是密度 不可知的(density-agnostic) ,系统不会缩放它们。
妳应当创建的替代资源的类型取决于妳的程序的需求。通常情况下,妳应当使用尺寸和方向标识符来提供替代的布局资源,而使用密度标识符来提供替代的位图绘图对象资源。
以下各个小节说明了,妳应当如何使用尺寸和密度标识符来分别提供替代的布局和绘图对象。
一般来说,当妳在不同的屏幕配置上测试妳的程序的时候,妳就会知道是否需要针对不同的屏幕尺寸来提供替代布局了。例如:
•.当妳在一个小屏幕上测试时,妳可能会发现妳的布局与当前屏幕不太相匹配。例如,在一个小屏幕设备上,一行按钮可能无法在屏幕所提供的宽度里装下去。在这种情况下,妳应当提供一个针对小屏幕的替代布局,在该布局中调整那些按钮的尺寸或位置。
•.当妳在一个超大屏幕上测试时,妳可能会意识到,妳的布局没有充分利用那么大个屏幕,显然是被拉伸到那么大了。在这种情况下,妳应当提供一个针对超大屏幕设计的替代布局,在其中重新设计用户界面以针对大屏幕例如平板做优化。
尽管妳的程序在不提供针对大屏幕的替代布局的情况下应该也能在大屏幕上正常显示,但是,对于用户来说,狠重要的一点就是,用户希望妳的程序看起来是专为他/她/它们的设备而设计过的。如果用户界面看起来显然是拉伸过的,那么,用户多半会对程序的使用体验不满意。
•.另外,当妳在测试时将横向模式与竖向模式对比时,妳可能会注意到,在竖向模式中被放置在屏幕底部的那些用户界面元素,在处于模式模式时应当放置到屏幕的右侧更为合适。
总结一下,妳应当确保妳的程序的布局满足以下要求:
•. 可以在小屏幕上正常显示(这样用户才能真正使用妳的程序)
•.针对较大的屏幕做了优化,以便利用额外的屏幕空间
•.针对横向模式和竖向模式都做了优化
如果 妳的用户界面中某个位图在系统缩放布局 的情况下仍然需要匹配某个视图的尺寸的话(例如某个按钮 的背景图片 ),那么 ,妳应当使用 点9 位图文件。 点9文件实际上是一个 PNG文件, 妳在这个文件中指定 可以被拉伸的二维区域。 当系统需要缩放带有这种位图的视图对象时,系统会跟着缩放该点9位图,但是只会缩放指定的区域。 这样,妳就不用针对不同的屏幕尺寸提供不同的绘图对象了,因为点9位图可以被调整到任意尺寸。然而 ,妳应当针对不同的屏幕密度提供替代版本的点9文件。
图 4. 支持每种密度 的位图绘图对象的相对尺寸。
注意 : 妳只需要为位图文件( .png 、 .jpg 或 .gif )及点9文件( .9.png )提供与密度相关的绘图对象。如果 妳使用 XML文件 来定义形状、颜色或其它 绘图资源 的话, 那么,妳应当将它们放置在默认的绘图对象目录( drawable/ )里。
要创建针对不同密度的替代位图绘图对象的话,妳应当将4种大致密度的绘图对象按照 3:4:6:8 的缩放比例 来设计。例如,如果妳的某个针对中等屏幕的位图绘图对象的尺寸是48x48 像素(启动图标的尺寸)的话,那么,其它的尺寸应当是:
•.36x36 ,低密度
•.48x48 ,中等密度
•.72x72 ,高密度
•.96x96 ,超高密度
欲知更多关于设计图标 的信息,则参考 图标设计指南 ,其中包 括各种各样的位图绘图对象的尺寸信息,例如启动图标、菜单图标、状态栏图标、标签栏图标及别的东西。
对于运行 着安卓3.0的第一代平板来说,用来声明平板布局 的方式就是将它们放置 在一个带有 xlarge 配置标识符的目录(例如 , res/layout-xlarge/ )中。 为了适应其它类型的平板和屏幕尺寸——特别是 7英寸 的平板——安卓 3.2引入 了一种新的方式来指定针对更加具体的屏幕尺寸的资源。 新的技巧是以妳的布局所需要的空间尺寸(例如600dp 的宽度 )为依据, 而不是尝试着让 妳的布局适配到4种大致尺寸分组(例如 large 或 xlarge )中。
在使用大致尺寸分组方式针对7英寸平板进行设计时, 狠需要费些劲(is tricky) ,因为 , 7英寸 的平板在技术上是与5英寸的掌上设备同属一个分组( large 组 )的。尽管 这两种设备的尺寸相近,但是,应用程序 的用户界面在这两种设备上能够使用的空间大小是有明显差别的,用户交互的风格也有差别。所以 , 7英寸 和 5英寸 的屏幕不应当总是使用相同的布局。 为了使妳能够针对这两种屏幕提供不同的布局,安卓现在允许妳根据实际可 被布局使 用 的宽度和/或高度来指定相应的布局资源, 其单位就是 dp 。
例如,在做好了针对平板类型的设备的布局设计之后,妳可能会发现,当屏幕的宽度小于600dp 时,该布局看起来可能不那么美观。因此,这就是妳的平板布局能够接受的最小尺寸。于是,妳可以指定,只有在屏幕中可用于布局的空间的尺寸最少为600dp 宽的时候,才能够使用这些布局资源。
妳可以选定一种宽度,然后将它作为妳能够接受的最小尺寸来进行设计,或者,在设计完成之后,通过测试来确定妳的布局所支持的最小宽度。
注意 : 记住,用于 这些新尺寸应用编程接口的所有参数,其值的单位都是与密度无关的像素(dp),并且 妳的布局中的各个参数也应当一直使用 dp作为单位 ,因为 ,妳真正关心 的只是 在系统将屏幕密度计算在内之后得到的屏幕空间的大小 (而不是单纯地看原始的像素分辨率) 。欲知更多关于 与密度无关的像素的信息,请阅读此文档中前面部分的 术语 和概念 。
表2中列出了妳在根据布局实际可用的空间进行布局资源指定时能够使用的不同的资源配置。与传统的屏幕尺寸分组(small、normal、large和xlarge)相比,这些新的标识符使得妳能够更加精细地控制妳的程序所能够支持的特定屏幕尺寸。
注意 : 妳使用这些标识符所指定的尺寸 并不是实际的屏幕尺寸 。而是 指的是, 能够 被妳的活动( activity )的窗口使用的 以 dp 为单位表示的宽度或高度。安卓系统可能 会使用屏幕中的一部分来显示系统用户界面 (例如屏幕底部 的系统栏,或者屏幕顶部的状态栏 ) ,所以 ,屏幕上的某些部分,对于妳的布局来说可能是不可用的。因此 , 妳所声明的尺寸,应当是专门指 妳的活动所需要的尺寸——系统 在声明妳的布局可以使用多少空间的时候,会将系统用户界面所占用的空间计算在内。另外需要注意 , 动作 栏 被认为是妳的程序的窗口空间中的一部分,尽管 妳的布局中没有声明它但是确实是这样计算的,所以 它又减少了妳的布局所能使用的空间,因此,妳在设计的时候必须将它也计算在内。
表 2. 用于屏幕尺寸 的新的配置标识符 ( 自安卓3.2开始引入 ) 。
屏幕配置 |
标识符值 |
说明 |
最小宽度 |
sw<N>dp
|
一个屏幕的基本尺寸,以可用的屏幕区域的最短边的长度来表示。 特别地,设备的最小宽度(smallestWidth),即为,屏幕上的可用高度和宽度中最短的那个值(妳还可以理解成该屏幕的"最小可能宽度")。妳可以使用这个标识符来确保,无论屏幕当前是什么方向的,妳的程序的用户界面都必须拥有 <N> dp的最少可用宽度。 例如,如果妳的布局要求屏幕可提供的最短边最少要达到600 dp的话,那么,妳可以使用这个标识符来创建对应的布局资源, res/layout-sw600dp/ 。系统只会在可用屏幕空间的最短边最少为600dp时才使用这些资源,这个过程中不管600dp的那个边是用户所认为的高度还是宽度。最小宽度是设备的一个固定的屏幕尺寸特性; 当屏幕的方向发生改变时,最小宽度不会发生改变。 设备的最小宽度,会将屏幕上的装饰内容和系统用户界面计算在内。例如,如果该设备屏幕上有一些固定的用户界面元素,占用了最小宽度所在方向上的空间的话,那么,系统会声明最小宽度比实际的屏幕尺寸要小,因为那些屏幕像素无法被妳的用户界面使用。 这是对于大致屏幕尺寸标识符(small、normal、large、xlarge)的一种替代手段,它使得妳能够定义一个针对妳的用户界面的有效可用尺寸的具体数值。使用最小宽度来确定屏幕尺寸是狠有用的,因为宽度通常是设计布局进所考虑的最重要因素。用户界面通常会在竖直方向上滚动,但是一般都会在水平方向上设置一个确定的最小空间限制。可用宽度的大小也是用来决定使用针对手机的单面板布局还是使用针对平板的多面板布局的关键因素。因此,妳可能最关心的就是每个设备上可能具有的最小宽度。 |
可用的屏幕宽度 |
w<N>dp
|
指定该资源对应的以dp为单位的最小可用宽度——具体数值由 <N> 的值来定义。当屏幕的方向在横向和竖向之间切换时,当前可用于妳的用户界面的实际可用宽度也会发生改变。 这个参数通常用于决定是否要采用多面板的布局,因为,即使是在平板设备上,妳通常也不希望像在横向模式那样对于竖向模式也使用多面板布局。因此,妳可以使用这个参数来指定当前布局所要求的最小宽度,而不用同时将屏幕尺寸和朝向标识符一起使用。 |
可用的屏幕高度 |
h<N>dp
|
指定该资源对应的以dp为单位的最小可用高度——具体数值由 <N> 的值来定义。当屏幕的方向在横向和竖向之间切换时,当前可用于妳的用户界面的实际可用高度也会发生改变。 就像使用 w<N>dp 来定义必需的宽度一样,使用这个参数来定义妳的布局所必需的高度也是狠有用的,而不需要同时将屏幕尺寸和朝向标识符一起使用。然而,大部分应用不需要这个标识符,因为用户界面通常会在竖直方向上滚动,因而对于可用高度来说,是更加灵活的,相比之下,对于宽度的要求更加严格。 |
看起来,使用这些标识符好像比使用屏幕尺寸分组更复杂,实际上,当妳确定好了妳的用户界面所需要的空间之后,它们应当会显得更简单。当妳在设计用户界面时,妳考虑的最主要的东西可能就是,妳的程序在手机风格的用户界面和平板风格的多面板用户界面之间切换时牵涉到的尺寸问题。具体的那个准确的切换点取决于妳的特定设计——可能妳的平板布局需要720dp的宽度,也可能600dp就足够了, 也可能是480dp,还有可能是位于这些数字之间的某个别的数字。 通过使用表2中的这些标识符,妳可以精确地控制好妳的布局会在什么条件下切换。
欲知更多关于 这些尺寸配置标识符的信息, 就 参考 提供资源 文档。
为了辅助妳更好地针对不同类型的设备做设计,以下列出一些典型的屏幕宽度:
•.320dp: 典型的手机屏幕(240x320 ldpi、320x480 mdpi、480x800 hdpi等等)。
•.480dp: 非主流(tweener)平板,例如Streak (480x800 mdpi)。
•.600dp: 7英寸平板(600x1024 mdpi)。
•.720dp: 10英寸平板(720x1280 mdpi、800x1280 mdpi等等)。
使用表2中的尺寸标识符,妳的程序可以根据任意的宽度和/或高度值来在针对手机和平板的不同布局之间切换。例如,如果600dp是妳的平板布局所支持的最小可用宽度,那么,妳可以提供这样两种布局:
res/layout/main_activity.xml # 针对手机
res/layout-sw600dp/main_activity.xml # 针对平板
在这个例子中,可用屏幕空间的最小宽度必须达到600dp,才会应用平板布局。
在其它情况下,如果妳想进一步区分7英寸和10英寸的平板来设计不同的布局的话,那么,妳还可以定义更多的最小宽度布局:
res/layout/main_activity.xml # 针对手机(没达到600dp的可用宽度)
res/layout-sw600dp/main_activity.xml # 针对7英寸平板(600dp宽或更宽)
res/layout-sw720dp/main_activity.xml # 针对10英寸平板(720dp宽或更宽)
注意 ,这里的两个示例资源中,使用了“最小宽度”标识符, sw<N>dp , 它指定的是屏幕两条 边中较小的那条, 与设备的当前朝向无关。因此 ,使用 sw<N>dp 是一种指定 可由妳的布局使用的整体屏幕尺寸的简单方法,它忽略了屏幕的朝向。
然而 ,在某些情况下,对于 妳的布局来说,重要的事情也许是, 当前 究竟 有多少宽度或高度是可用的。例如,如果 妳有一个双栏的布局,其中并排着两个片断(fragments),那么 , 妳可能会在确定提供 了最小 600dp宽度 的情况下使用该布局,而不管当前设备 是处于横向模式还是竖向模式。 在这种情况下,资源应当是这样声明的:
res/layout/main_activity.xml # 针对手机(没达到600dp的可用宽度)
res/layout-w600dp/main_activity.xml # 多面板(拥有600dp的可用宽度或更大宽度的任意屏幕)
注意 ,这个示例里使用的是“可用宽度”标识符, w<N>dp 。通 过这种方式 的声明 , 同一个设备是有可能将两种布局都用上的,具体使用哪种布局就取决于屏幕的朝向(例如 在一个朝向下可用的宽度已经达到 600dp ,而在另一个朝向下,可用宽度小于 600dp)了。
如果 妳需要考虑可用高度的话,那么, 妳可以使用 h<N>dp 标识符来做类似的事情。 或者,如果妳真的需要做到非常精确的话,甚至可以将 w<N>dp 和 h<N>dp 标识符组合起来使用。
当妳针对不同屏幕尺寸设计好了布局之后,还有一件事同样重要,那就是,在清单文件中声明妳的程序所支持的屏幕尺寸。
除了针对屏幕尺寸的新的配置标识符以外,安卓 3.2 还为清单文件中的 <supports-screens> 元素引入了新的属性:
android:requiresSmallestWidthDp
指定 的是所要求的最小的最小宽度(smallestWidth)。最小宽度 ( smallestWidth )指的是, 可被妳的程序用户界面使用的 屏幕空间 ( 以 dp 为单位 )的两条边中较小那条边 。所以 , 一个设备的最小宽度必须等于或大于这个值,才会被认为是与妳的程序兼容的。 (通常情况 下,妳所指定的这个值表示的是妳的布局所支持的“最小宽度”,并且这与屏幕的当前朝向无关。 )
例如,如果妳的程序只是针对拥有600dp 的最小可用宽度的平板设备设计的:
<manifest ... >
<supports-screens android:requiresSmallestWidthDp="600" />
...
</manifest>
然而,如果妳的程序支持所有被安卓支持的屏幕的话(最小可能是426dp x 320dp),那么,妳不需要声明这个属性,因为妳的程序所要求的最小宽度实际上是任意设备都能达到的最小宽度。
警告: 安卓系统 不会实际采纳 这个属性,所以,它不会影响到 妳的程序在运行时的表现。 这个属性的实际作用是, 在一些外部服务中 用来过滤 出妳的程序,例如 Google Play 。然而 , Google Play 目前 不支持按照这个属性进行过滤 ( 在安卓 3.2 上 ) ,所以 ,如果妳的程序不支持小屏幕的话,妳应当继续使用其它 的那些尺寸属性。
android:compatibleWidthLimitDp
这个属性使得妳可以 以一个用户可选特性的方式来启用 屏幕兼容模式 ,具体 地,就是,指定 妳的程序所支持的最大的“最小宽度”。如果某个设备 的可用屏幕的最短边 比妳这个值还要大的话,那么,用户仍然可以安装妳的程序,但是, 会以一种屏幕兼容模式来运行它。默认情况 下,屏幕兼容模式处于禁用状态,妳的布局会 像通常那样被改变大小以填满屏幕,但是在系统栏中会显示一个按钮,用户 可以通过那个按钮来切换屏幕兼容模式。
注意 : 如果 妳的程序的布局能够在大屏幕上正确显示的话,妳就不需要使用这个属性。 我们建议,妳避免使用这个属性, 而应当按照本文档中的那些建议来设计 ,以确保妳的布局在大屏幕上也能正常显示。
这个属性使得妳能够强制启用 屏幕兼容模式 ,具体 地就是,指定 妳的程序所支持的最大的“最小宽度”。如果某个设备 的可用屏幕的最短边比妳设置的这个值还要大,则,程序会运行于屏幕兼容模式,用户无法禁用 它。
注意 : 如果 妳的程序的布局能够在大屏幕上正确显示的话,妳就不需要使用这个属性。 我们建议,妳避免使用这个属性, 而应当按照本文档中的那些建议来设计 ,以确保妳的布局在大屏幕上也能正常显示。
警告: 如果 妳开发的目标系统版本是安卓 3.2 及更高版本,那么 , 妳 不应当将之前那些 旧的屏幕尺寸属性与这里列出的属性组合起来使用。 同时使用旧属性和新属性的话,可能引起未知的行为。
欲知关于这些属性的更多信息,就点击上面相应的链接。
对多种屏幕提供支持,其目的是,创建一个在安卓所支持的任何一种大致屏幕尺寸配置的设备上都能够正确运行并且外观精美的程序。本文档中之前的小节,说明了,安卓如何将妳的程序适配到不同的屏幕配置上去,以及,妳应当如何调整程序在不同屏幕配置情况下的外观。本小节提供了一些额外的提示,以及一个技巧概述,可以帮助妳确保妳的程序在不同的屏幕配置情况下也能适当的缩放。
这是一份快速核对单,是一些关于如何让妳的程序在不同屏幕上适当显示的信息:
1. 在XML 布局文件中指定尺寸时,使用 wrap_content 、 fill_parent 或以 dp 作为单位
2.不要在程序代码中使用硬编码的像素值
3. 不要使用 AbsoluteLayout ( 这个元素已废弃 )
4.针对不同的屏幕密度提供替代的位图绘图对象
以下各小节提供更详细的说明。
在XML 布局文件中定义视图的 android:layout_width 和 android:layout_height 时,使用 "wrap_content" 、 "fill_parent" 或以 dp 作为单位 ,可确保 该视图在当前设备的屏幕上得到一个合适的尺寸。
例如,某个视图 的 layout_width="100dp" ,则 ,在中等密度的屏幕上, 它的实际宽度是 100像素 ,而在高密度的屏幕上,系统会将它放大至 150像素宽 , 这样,该视图在不同屏幕上占据着几乎相同大小的物理空间。
类似 地,妳应当优先使用 sp ( 与缩放无关的像素( scale-independent pixel ) ) 来定义文字的尺寸。 sp 的缩放因子取决于某个用户设置选项,系统 会像对待 dp 一样地将文字的尺寸进行缩放。
出于性能原因,并且为了保持代码的简单,安卓系统使用像素 值作为表达尺寸和坐标的标准单位。 这就意味着,每个视图的实际尺寸,在代码中一直是使用像素值来表示的,但是都是经过了与当前屏幕的密度相关的换算的。例如,如果 myView.getWidth() 返回10 ,则,该视图在当前屏幕上的宽度是 10 个像素,但是,在一个拥有更高密度屏幕的设备上,所返回的值可能会是 15 。如果 妳在程序代码中使用像素值来处理那些未针对当前屏幕密度做预缩放的位图的话,那么 , 妳可能需要缩放妳的程序代码中所使用的像素值,以匹配那些 未经过缩放的位图。
如果 妳的程序会在运行时处理位图或操作像素值的话,则参考下面 的 额外 的密度考量 小节。
与其它布局部件不同的是, AbsoluteLayout 强制使用固定 的位置来对子代视图进行布局, 这就狠容易导致用户界面在不同的屏幕上走样。因为这一点, AbsoluteLayout 从安卓1.5(应用编程接口版本 3 )开始就被废弃了。
妳应当使用 RelativeLayout 作为替代, 它会使用相对位置 来对子代视图进行布局。例如, 妳可以指定,某个按钮应当位于某个文字部件的“右侧”。
尽管系统会按照当前屏幕的配置来缩放妳的布局和绘图资源,但是,妳可能还是需要针对不同的屏幕尺寸来调整用户界面,并且提供针对不同密度做了优化的位图绘图对象。这其实是重复地说了本文档中之前所说的那些信息。
如果妳需要精确地控制住妳的程序在各种屏幕配置情况下的外观的话,那么,调整各个与配置相关的资源目录中的布局和位图绘图对象。例如,假设妳想在中等和高密度的屏幕上显示一个图标。只需简单地按照两种尺寸创建妳的图标(例如,针对中等密度设计成100x100,针对高密度设计成150x150),再使用适当的标识符来将这两个版本的图标放置在相应的目录中:
res/drawable-mdpi/icon.png //针对中等密度的屏幕
res/drawable-hdpi/icon.png //针对高密度的屏幕
注意 : 如果某个目录 名中不带密度标识符,那么,系统会假设该目录中的资源是针对基准的中等密度设计的,并且 会针对其它密度做相应的缩放。
欲知更多关于 有效的配置标识符的信息,参考本文档中之前的 使用配置标识 符 。
这个小节,更详细地说明了,安卓如何针对不同的屏幕密度对位图绘图对象进行缩放,以及,妳可以如何进一步地控制位图在不同密度情况下的显示情况。对于大部分的应用程序来说,这个小节中的信息应当是不重要的,除非妳的程序在运行于不同密度的屏幕上时出现问题,或者妳的程序本身就需要对图像进行操作。
为了更好地理解妳的程序于运行时操作图像时该如何支持多种屏幕密度,妳首先应当理解,系统通过以下手段来帮助确保位图被适当地缩放了:
1. 资源(例如位图绘图对象) 的预缩放
基于当前屏幕的密度,系统会使用妳程序中任何能找到的与尺寸或密度相关的资源,并且在不缩放的情况下显示它们。如果找不到对应于正确密度的资源,那么,系统会载入默认的资源,并且对它们进行放大或缩小,以匹配当前屏幕的密度。系统假设,默认资源(从不带配置标识符的目录中找到的资源)是针对基准屏幕密度(mdpi)设计的,除非它们是从一个与密度相关的资源目录中载入的。因此,预缩放指的是,系统针对当前屏幕的密度,将一个位图缩放到适当的尺寸。
如果 妳询问某个预缩放后的资源的尺寸信息的话,系统会返回缩放 之后 的尺寸值。例如, 一个针对mdpi 屏幕设计的50x50 像素的位图, 在hdpi 屏幕上会被缩放到75x75 像素(如果 没有针对 hdpi 的替代资源的话 ),系统 会报告后一个尺寸。
在某些情况下,妳可能不想让安卓对某个资源进行预缩放。 最简单地避免预缩放的手段就是,将该资源放置到一个带有 nodpi 配置标识符的资源目录中。例如:
res/drawable-nodpi/icon.png
当系统使用 这个目录 中的 icon.png 位图时, 不会按照当前设备 的密度进行缩放。
2. 针对像素尺寸数据 和坐标进行自动缩放
一个应用程序可在清单文件中将 android:anyDensity 设置成 "false" 以禁用预缩放,或者使用代码 来将某个具体 Bitmap 的 inScaled 设置成 "false" 以禁用该对象的预缩放。 在这种情况下,系统 会在渲染时刻自动地缩放任何的绝对像素坐标及像素尺寸值。 它做这些操作,是为了确保, 以像素值定义的那些屏幕元素,仍然会呈现 出几乎 与它们在基准屏幕密度(mdpi)上所显示出的相同的物理尺寸。系统 以一种对程序来说透明的方式来处理这种缩放过程,并且 将缩放后得到的像素尺寸值报告给应用程序, 而不是报告物理的像素尺寸。
举例 来说,假设 有一个设备,它拥有一个 WVGA 高密度屏幕,也就是 480x800 ,并且尺寸 与传统的HVGA 屏幕相同,但是 这个设备上运行的某个程序禁用了预缩放。 在这种情况下,系统 会在该程序查询屏幕尺寸时对它“撒谎”,并且报告 为 320x533 (针对当前屏幕密度翻译 为mdpi 得到的近似值 ) 。然后 , 当程序进行绘图操作时,例如 将(10,10)到(100, 100)的矩形区域标记为无效,系统 会对坐标进行缩放变换,最终实际 上将(15,15)到(150, 150)的区域标记为无效。 如果妳的程序会直接对缩放后的位图进行操作的话,这种差异可能会引起未知的行为,但是, 这被认为是一个合理的代价,以确保程序 的性能尽可能好。如果 妳遇到这种问题的话,就阅读下面小节 中的 将 单位转换 成像素单位 。
通常情况 下, 妳不应当禁用预缩放。 用于 对多种屏幕提供支持的最佳方法就是按照之前 在 如何支持多种屏幕 中所说明的基本技巧来做。
如果妳的程序会对位图进行操作,或者以别的某种形式与屏幕上的像素进行交互的话,那么,妳可能需要采取额外的步骤来支持不同的屏幕密度。例如,如果妳通过记录手指滑过的像素点的个数来对触摸手势做出响应的话,那么,妳需要使用相应的与密度无关的像素值,而不是使用实际的像素值。
图 5. 来自 于 ApiDemos , 预缩放和自动缩放的位图之间的对比 。
要想控制在运行时创建的 Bitmap 对象是否会被缩放的话, 妳可以使用 setDensity() 来指定该位图的密度, 其参数就是 DisplayMetrics 中的某个密度常量,例如 DENSITY_HIGH 或 DENSITY_LOW 。
如果 妳使用 BitmapFactory 来创建 Bitmap 的话,例如 从一个文件或一个流中读取位图,那么, 妳可以使用 BitmapFactory.Options 来定义已经存在的位图的属性, 这些属性会用来决定系统是否要对它缩放,以及如何缩放。例如, 妳可以使用 inDensity 字段 来定义 出该位图是针对哪种密度而设计的,使用 inScaled 字段 来指定 该位图是否应当被缩放以匹配当前设备 的屏幕密度。
如果 妳将 inScaled 字段设置 为 false ,那么, 妳就禁用了系统可能会对该位图应用的预缩放,于是系统 就会在绘图时对它进行自动缩放。使用自动缩放 而不是预缩放的话, 会耗费更多的 CPU资源 ,但是 会使用较少的内存。
图 5展示 的是, 在一个高密度屏幕上,载入 低(120) 、 中(160) 和 高(240) 密度位图时, 预缩放和自动缩放机制产生的效果比较。两者 的差别是微妙的,因为所有 的位图都被缩放到匹配当前屏幕密度,然而 , 经过预缩放以及在绘图时刻自动缩放的位图之间,外观上 还是稍微有点不同。 妳可以在 ApiDemos 中找到这个示例程序的源代码, 它演示了对位图进行预缩放和自动缩放。
注意 : 在安卓3.0及更高版本的系统中,由于图像框架 的改进, 在预缩放和自动缩放的位图之间应当不会再有明显可察觉的差异了。
在某些情况下,妳可能会需要以 dp 为单位来表达尺寸信息,然后将它们转换成像素值。想象 一下,在某个程序中, 当用户的手指移动 了最少16个像素时,会识别成一个滚动或惯性滚动 (fling)手势。 在一个基准密度的屏幕上, 为了触发这个手势,用户必须 将手指移动 16 像素 / 160 dpi ,即为 1/10英寸( 或 2.5 mm) 。 而在一个高密度屏幕 (240dpi) 的设备上,用户必须 将手指移动 16 像素 / 240 dpi ,即为 1/15英寸( 或 1.7 mm) 。 这个距离就要短得多了,于是程序就显得更加地灵敏。
为了解决这个问题,必须以 dp 为单位来表示这个手势的阈值, 再将它的值转换成像素值。例如:
// 以dp为单位来表示这个手势的阈值
private static final float GESTURE_THRESHOLD_DP = 16.0f;
// 获取屏幕的密度缩放值
final float scale = getResources() . getDisplayMetrics() .density;
// 按照密度缩放值,将dp单位转换成像素单位
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);
// 将mGestureThreshold 作为以像素值为单位的距离来使用……
DisplayMetrics.density 字段 ,表示的是,按照当前 的屏幕密度, 当妳将 dp 单位转换成像素值单位时,必须使用的缩放因子。 在一个中等密度的屏幕上, DisplayMetrics.density 等于1.0 ; 在一个高密度屏幕上,它等于 1.5 ;在一个超高密度屏幕上,它等于 2.0 ;在一个低密度屏幕上,它等于 0.75 。 ( ☯: 在OPPO Find5 X909手机上,这个值等于3.0 ) 这个值的意思是, 要想获取某个以 dp 为单位的值在当前屏幕上对应 的实际像素个数,应当 将该值乘以这个属性的值。 (然后 ,在转换为一个整数目标值 时 ,还要加上 0.5f ,以四舍五入得到最接近的整数值。 ) 欲知更多信息, 就参考 DisplayMetrics 类。
然而 ,对于 这种类型 的事件,除了定义一个任意的阈值以外,还有一种更好的处理方法, 妳应当使用 ViewConfiguration 中提供的那些预缩放过的配置值。
妳可以使用 ViewConfiguration 类来获取到安卓系统所使用的一些常用距离、速度和时间长度值。 举个例子, 可使用 getScaledTouchSlop() 来获取到框架中用来作为滚动动作阈值的以像素为单位的距离 值 :
private static final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();
ViewConfiguration 中,以 getScaled 前缀开头的那些方法,能够确保 ,它们 所返回的以像素为单位的值能够 在不理会当前屏幕密度的情况下正确显示。
图 6. 一组用来测试屏幕支持情况的安卓虚拟设备。
要想建立一个环境来测试妳的程序的屏幕支持情况的话,妳需要创建一系列的安卓虚拟设备(AVD)(Android Virtual Devices),并且在创建过程中使用不同的模拟器皮肤和屏幕配置参数来模拟妳希望由妳的程序所支持的屏幕尺寸和密度。为了做到这一点,妳可以使用安卓虚拟设备管理器来创建那些安卓虚拟设备,再使用一个图形界面来启动它们。
要启动安卓软件开发工具包管理器的话,就执行 <sdk>/tools/ 目录 中的 android 。 图 6 中显示了安卓虚拟设备管理器,以及一个用于测试屏幕配置的安卓虚拟设备。
表3中列出了安卓软件开发工具包中自带的多种模拟器皮肤,妳可以使用它们来模拟那些最常见的屏幕配置情况。
欲知更多关于创建 及使用安卓虚拟设备来测试妳的程序的信息,参考 使用安卓虚拟设备管理 器来管理安卓虚拟设备 。
表 3. 安卓软件开发工具 包的模拟器皮肤所提供的各种屏幕配置( 以粗体表示 )以及其它 可表示的分辨率。
低密度 (120), ldpi |
中等密度 (160), mdpi |
高密度 (240), hdpi |
超高密度 (320), xhdpi |
|
小 屏幕 |
QVGA (240x320) |
480x640 |
||
普通 屏幕 |
WQVGA400 (240x400)
|
HVGA (320x480) |
WVGA800 (480x800)
|
640x960 |
大 屏幕 |
WVGA800** (480x800)
|
WVGA800* (480x800)
|
||
超大 屏幕 |
1024x600 |
WXGA (1280x800)
† |
1536x1152 |
2048x1536 |
* 要想模拟这种配置的话,在创建一个使用WVGA800 或WVGA854 皮肤的安卓虚拟设备时,指定自定义密度为160。
|
要想查看支持各种指定屏幕配置情况的活跃设备的相对数量的话,参考 屏幕尺寸 和密度 面板 。
图 7. 从安卓虚拟设备管理器中启动一个安卓虚拟设备时,可以设置屏幕尺寸和密度。
如果内置的皮肤不支持妳想测试的目标屏幕所使用的分辨率或密度的话,那么,妳可以创建一个新的安卓虚拟设备,让它使用自定义的分辨率或密度。在安卓虚拟设备管理器中创建安卓虚拟设备时,指定具体的分辨率,而不要选择某种内置的皮肤。
如果 妳是通过命令行来启动安卓虚拟设备的,那么, 妳可以使用 -scale 选项来指定模拟器的缩放比例。例如:
emulator -avd <avd_name> -scale 96dpi
要想更精细地调整模拟器的尺寸的话, 妳可以向 -scale 选项传递 一个位于 0.1 到 3之间 的数值, 它代表着预期的缩放因子。
欲知更多关于 从命令行来创建安卓虚拟设备 的信息,则参考 通过命令 行来管理安卓虚拟设备
江伊涵
高跟鞋
S
HxLauncher: Launch Android applications by voice commands